package com.shawn.es.demo;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.delete.DeleteIndexRequest;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.support.master.AcknowledgedResponse;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.client.indices.GetIndexRequest;
import org.elasticsearch.client.indices.GetIndexResponse;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentBuilder;
import org.elasticsearch.common.xcontent.XContentFactory;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MatchAllQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;

public class ElasticSearchClientTest {

	private static final String INDEX = "test_client";

	private static final String TYPE = "_doc";

	public static void main(String[] args) throws Exception{
		RestHighLevelClient client = null;
		try {
			client = new RestHighLevelClient(
				RestClient.builder(
					new HttpHost("192.168.1.105", 9200, "http")));
			//createData(client);
//			getIndex(client);
//			System.out.println("update before: ");
//			getDocumentById(client,"1");
//			updateDocById(client);
//			System.out.println("update after : ");
//			getDocumentById(client,"1");
//			System.out.println("delete before: ");
//			getDocumentById(client,"2");
//			deleteDocById(client,"2");
//			System.out.println("delete after: ");
//			getDocumentById(client,"2");
//			batchCreateData(client);
			query(client);
		}catch (Exception e){
			e.printStackTrace();
		}finally {
			if(client != null){
				client.close();
			}
		}


	}

	private static void createData(RestHighLevelClient client) throws Exception {
		List<IndexRequest> requests = Arrays.asList(createIndexByParams(),createIndexByJsonString(),
			createIndexByMap(),createIndexByXContentBuilder());
		for (int i = 0; i < requests.size(); i++) {
			IndexRequest request = requests.get(i);
			IndexResponse indexResponse = client.index(request, RequestOptions.DEFAULT);
			RestStatus status = indexResponse.status();
			if(status == RestStatus.CONFLICT){
				throw new RuntimeException("冲突");
			}
			System.out.println("成功创建索引！");
		}
	}

	private static IndexRequest createIndexByParams(){
		IndexRequest request = new IndexRequest(INDEX)
			.id("4")
			.source("user", "kimchy",
				"postDate", new Date(),
				"message", "trying out Elasticsearch");
		request.type(TYPE);
		return request;
	}

	private static IndexRequest createIndexByXContentBuilder() throws Exception {
		XContentBuilder builder = XContentFactory.jsonBuilder();
		builder.startObject();
		{
			builder.field("user", "kimchy");
			builder.timeField("postDate", new Date());
			builder.field("message", "trying out Elasticsearch");
		}
		builder.endObject();
		IndexRequest request = new IndexRequest(INDEX)
			.id("3").source(builder);
		request.type(TYPE);
		return request;
	}

	private static IndexRequest createIndexByMap(){
		Map<String, Object> jsonMap = new HashMap<>();
		jsonMap.put("user", "kimchy");
		jsonMap.put("postDate", new Date());
		jsonMap.put("message", "trying out Elasticsearch");
		IndexRequest request = new IndexRequest(INDEX)
			.id("2").source(jsonMap);
		request.type(TYPE);
		return request;
	}

	private static IndexRequest createIndexByJsonString(){
		IndexRequest request = new IndexRequest(INDEX);
		request.id("1");
		request.type(TYPE);
		String jsonString = "{" +
			"\"user\":\"kimchy\"," +
			"\"postDate\":\"2013-01-30\"," +
			"\"message\":\"trying out Elasticsearch\"" +
			"}";
		request.source(jsonString, XContentType.JSON);
		return request;
	}

	private static void getIndex(RestHighLevelClient client) throws Exception{
		GetIndexRequest request = new GetIndexRequest(INDEX);
		GetIndexResponse indexResponse = client.indices().get(request, RequestOptions.DEFAULT);
		System.out.println(Arrays.toString(indexResponse.getIndices()));
		boolean exists = client.indices().exists(request, RequestOptions.DEFAULT);
		System.out.println(exists);
	}

	private static void deleteIndex(RestHighLevelClient client) throws Exception{
		DeleteIndexRequest request = new DeleteIndexRequest(INDEX);
		AcknowledgedResponse delete = client.indices().delete(request, RequestOptions.DEFAULT);
		boolean acknowledged = delete.isAcknowledged();
		System.out.println(acknowledged);
	}

	private static void getDocumentById(RestHighLevelClient client, String id) throws Exception{
		GetRequest request = new GetRequest(INDEX);
		request.id(id);
		request.type(TYPE);
		GetResponse response = client.get(request, RequestOptions.DEFAULT);
		boolean exists = response.isExists();
		if(exists){
			response.getSource().forEach((k ,v) -> {
				System.out.printf("key: %s, value: %s \n", k, v);
			});
		}
	}

	private static void updateDocById(RestHighLevelClient client) throws Exception{
		UpdateRequest request = new UpdateRequest(INDEX,TYPE,"1");
		Map<String, Object> map = new HashMap<>();
		map.put("user", "Shawn");
		map.put("postDate", new Date());
		map.put("message", "try update api");
		request.doc(map);
		UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
		System.out.println(response.status());
	}

	private static void deleteDocById(RestHighLevelClient client, String id) throws Exception{
		DeleteRequest request = new DeleteRequest(INDEX,TYPE,id);
		request.timeout("1s");
		DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
		System.out.println(response.status());
	}

	private static void batchCreateData(RestHighLevelClient client) throws Exception{
		BulkRequest request = new BulkRequest();
		List<Map<String, Object>> mapList = new ArrayList<>();
		for (int i = 0; i < 10; i++) {
			Map<String, Object> map = new HashMap<>();
			map.put("user", "shawn_" + (i + 1));
			TimeUnit.MILLISECONDS.sleep(500);
			map.put("postDate", new Date());
			map.put("message", "try batch create Data");
			mapList.add(map);
		}

		for (int i = 0; i < mapList.size(); i++) {
			Map<String, Object> jsonMap = mapList.get(i);
			IndexRequest indexRequest = new IndexRequest(INDEX)
				.id(((i + 1) * 10) + "").source(jsonMap).type(TYPE);
			request.add(indexRequest);
		}
		BulkResponse bulk = client.	bulk(request, RequestOptions.DEFAULT);
		System.out.printf("是否有失败的?  ->> %s \n", bulk.hasFailures());
	}

	private static void query(RestHighLevelClient client) throws Exception{
		SearchRequest request = new SearchRequest(INDEX);
		request.types(TYPE);
		SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();

//		MatchAllQueryBuilder matchAllQueryBuilder = QueryBuilders.matchAllQuery();
		MatchQueryBuilder matchQueryBuilder = QueryBuilders.matchQuery("user", "shawn");
		searchSourceBuilder.query(matchQueryBuilder);
		searchSourceBuilder.sort("postDate");
		searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
		request.source(searchSourceBuilder);
		SearchResponse search = client.search(request, RequestOptions.DEFAULT);
		SearchHits hits = search.getHits();
		Iterator<SearchHit> iterator = hits.iterator();
		while (iterator.hasNext()){
			SearchHit next = iterator.next();
			Map<String, Object> sourceAsMap = next.getSourceAsMap();
			sourceAsMap.forEach((k, v) -> {
				System.out.printf("key: %s,\tvalue: %s\n",k,v);
			});
		}
	}
}
